# -*- coding: utf-8 -*-
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# 15-Jul-2016   Brendan Gregg   Created this.
# 20-Oct-2016      "      "     Switched to use the new 4.9 support.
# 26-Jan-2019      "      "     Changed to exclude CPU idle by default.

from __future__ import print_function
from multiprocessing import  Process
# from ast import arg
import sys
import os
import cybertron
#from protopy import soa2anp_pb2
from protopy import perfanp_pb2

from sys import stderr
from time import sleep
import argparse
import signal
import errno
import time
from datetime import datetime
import threading
import traceback
import subprocess
import signal

# arguments
examples = """examples:
    ./profile --dir /opt/log    # profile stack traces at 49 Hertz until Ctrl-C
"""
parser = argparse.ArgumentParser(
    description="trigger profile",
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog=examples)
parser.add_argument("--dir",
    help="choose the directory you want to choose"
)
args = parser.parse_args()

master_slave_board = os.environ.get('MASTER_SLAVE', 'master')
last_trigger_time = time.time()
log_count = 0
outfile = ""
log_interval = 150
pre_drive_mode = perfanp_pb2.MANU
pre_drive_domain = perfanp_pb2.URBAN
file_lock = threading.Lock()
def profile_trigger(msg, pid):
    """
    将消息转储到文件中
    
    Args:
    msg: 要写入文件的字符串。
    
    Returns:
    无返回值。
    
    """
    # print('cond trigger')
    trigger_board = msg.master_or_slave
    can_trigger = False
    if (trigger_board == perfanp_pb2.ALL):
        # print('trigger all')
        can_trigger = True
    elif (master_slave_board == "master" and trigger_board == perfanp_pb2.MASTER):
        # print('trigger master')
        can_trigger = True
    elif (master_slave_board == "slave" and trigger_board == perfanp_pb2.SLAVE):
        # print('trigger slave')
        can_trigger = True
    else:
        # print('trigger: ', trigger_board)
        return

    global last_trigger_time
    if time.time() - last_trigger_time > 1.2:
        os.kill(pid, signal.SIGUSR1)
        last_trigger_time = time.time()
    else:
        # print('profile_trigger less than 1s')
        return
    file_lock.acquire()
    global log_count
    global outfile
    global log_interval
    if (log_count % log_interval == 0 ):
        outfile = open("{}/bcc_profile.log.reason.{}.{}".format(args.dir,time.strftime("%y%m%d-%H%M%S", time.localtime()),str(os.getpid())),"w+",2**12)
    log_count = log_count + 1
    curtime = datetime.now()
    curtime_str = curtime.strftime('%Y-%m-%d %H:%M:%S')
    outfile.write(curtime_str + " bcc_profile trigger reason: " + msg.warning_name + " value: " + str(msg.trigger_value))
    outfile.write("\n")
    file_lock.release()

def flush_trigger(msg, pid):
    """
    将消息转储到文件中
    
    Args:
    msg: 要写入文件的字符串。
    
    Returns:
    无返回值。
    
    """
    # print('cond trigger')
    global pre_drive_mode
    cur_drive_mode = msg.drive_mode
    if (cur_drive_mode == perfanp_pb2.MANU and pre_drive_mode == perfanp_pb2.AUTO):
        file_lock.acquire()
        # print('trigger flush')
        global outfile
        if (outfile):
            outfile.flush()
        file_lock.release()     
    pre_drive_mode = cur_drive_mode

    global pre_drive_domain
    if (pre_drive_domain != msg.drive_domain):
        pre_drive_domain = msg.drive_domain

def create_profile_trigger(pid):
    # create reader to get listen from profile_warning
    profile_node = cybertron.node.Node("profile_test")
    # print('create node')
    profile_node.create_reader("/perf/profile_warning", perfanp_pb2.ProfileWarning, profile_trigger, pid)
    # print('create reader')
    profile_node.create_reader("/perf/perf_master", perfanp_pb2.Perfmessage, flush_trigger, pid)
    profile_node.spin()
    # print('close outfile')
    if (outfile):
        outfile.close()

def get_pid(name):
    cmd = "pgrep -f '" + name + "'"
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    output = process.stdout.read()
    pids = output.strip().split('\n')
    if pids:
        return int(pids[0])
    else:
        return 0

try:
    print('get python2 profile pid')
    pid = get_pid("python2 /opt/anp/bin/profile")
    print(pid)
    if pid == 0:
        exit()
    create_profile_trigger(pid)

except Exception as e:
    print("An error occurred:", e)